package com.example.backend.service;

import com.example.backend.domain.enums.TicketPriority;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.Instant;
import java.util.Map;

/**
 * 工单优先级管理系统
 * 管理紧急、高、中、低四个等级的优先级规则和SLA时间
 */
@Service
public class TicketPriorityManagementService {

    /**
     * 优先级配置信息
     */
    private static final Map<TicketPriority, PriorityConfig> PRIORITY_CONFIGS = Map.of(
        TicketPriority.URGENT, new PriorityConfig(
            "紧急", 
            Duration.ofHours(2),    // 2小时内响应
            Duration.ofHours(8),   // 8小时内解决
            "#dc3545",             // 红色
            100                    // 权重
        ),
        TicketPriority.HIGH, new PriorityConfig(
            "高", 
            Duration.ofHours(4),    // 4小时内响应
            Duration.ofHours(24),  // 24小时内解决
            "#fd7e14",             // 橙色
            80                     // 权重
        ),
        TicketPriority.MEDIUM, new PriorityConfig(
            "中", 
            Duration.ofHours(8),    // 8小时内响应
            Duration.ofDays(3),    // 3天内解决
            "#ffc107",             // 黄色
            60                     // 权重
        ),
        TicketPriority.LOW, new PriorityConfig(
            "低", 
            Duration.ofDays(1),     // 1天内响应
            Duration.ofDays(7),    // 7天内解决
            "#28a745",             // 绿色
            40                     // 权重
        )
    );

    /**
     * 优先级配置类
     */
    public static class PriorityConfig {
        private final String displayName;
        private final Duration responseTimeSLA;
        private final Duration resolutionTimeSLA;
        private final String color;
        private final int weight;

        public PriorityConfig(String displayName, Duration responseTimeSLA, Duration resolutionTimeSLA, String color, int weight) {
            this.displayName = displayName;
            this.responseTimeSLA = responseTimeSLA;
            this.resolutionTimeSLA = resolutionTimeSLA;
            this.color = color;
            this.weight = weight;
        }

        public String getDisplayName() { return displayName; }
        public Duration getResponseTimeSLA() { return responseTimeSLA; }
        public Duration getResolutionTimeSLA() { return resolutionTimeSLA; }
        public String getColor() { return color; }
        public int getWeight() { return weight; }
    }

    /**
     * 获取优先级配置
     * 
     * @param priority 优先级
     * @return 优先级配置
     */
    public PriorityConfig getPriorityConfig(TicketPriority priority) {
        return PRIORITY_CONFIGS.get(priority);
    }

    /**
     * 获取优先级的显示名称
     * 
     * @param priority 优先级
     * @return 显示名称
     */
    public String getPriorityDisplayName(TicketPriority priority) {
        PriorityConfig config = PRIORITY_CONFIGS.get(priority);
        return config != null ? config.getDisplayName() : priority.name();
    }

    /**
     * 获取优先级的颜色
     * 
     * @param priority 优先级
     * @return 颜色代码
     */
    public String getPriorityColor(TicketPriority priority) {
        PriorityConfig config = PRIORITY_CONFIGS.get(priority);
        return config != null ? config.getColor() : "#6c757d";
    }

    /**
     * 获取优先级的权重
     * 
     * @param priority 优先级
     * @return 权重值
     */
    public int getPriorityWeight(TicketPriority priority) {
        PriorityConfig config = PRIORITY_CONFIGS.get(priority);
        return config != null ? config.getWeight() : 0;
    }

    /**
     * 计算响应时间SLA
     * 
     * @param priority 优先级
     * @param createdAt 工单创建时间
     * @return SLA截止时间
     */
    public Instant calculateResponseSLA(TicketPriority priority, Instant createdAt) {
        PriorityConfig config = PRIORITY_CONFIGS.get(priority);
        if (config == null) {
            return createdAt.plus(Duration.ofDays(1)); // 默认1天
        }
        return createdAt.plus(config.getResponseTimeSLA());
    }

    /**
     * 计算解决时间SLA
     * 
     * @param priority 优先级
     * @param createdAt 工单创建时间
     * @return SLA截止时间
     */
    public Instant calculateResolutionSLA(TicketPriority priority, Instant createdAt) {
        PriorityConfig config = PRIORITY_CONFIGS.get(priority);
        if (config == null) {
            return createdAt.plus(Duration.ofDays(7)); // 默认7天
        }
        return createdAt.plus(config.getResolutionTimeSLA());
    }

    /**
     * 检查是否违反响应时间SLA
     * 
     * @param priority 优先级
     * @param createdAt 工单创建时间
     * @param firstResponseAt 首次响应时间
     * @return 是否违反SLA
     */
    public boolean isResponseSLAViolated(TicketPriority priority, Instant createdAt, Instant firstResponseAt) {
        if (firstResponseAt == null) {
            return Instant.now().isAfter(calculateResponseSLA(priority, createdAt));
        }
        return firstResponseAt.isAfter(calculateResponseSLA(priority, createdAt));
    }

    /**
     * 检查是否违反解决时间SLA
     * 
     * @param priority 优先级
     * @param createdAt 工单创建时间
     * @param resolvedAt 解决时间
     * @return 是否违反SLA
     */
    public boolean isResolutionSLAViolated(TicketPriority priority, Instant createdAt, Instant resolvedAt) {
        if (resolvedAt == null) {
            return Instant.now().isAfter(calculateResolutionSLA(priority, createdAt));
        }
        return resolvedAt.isAfter(calculateResolutionSLA(priority, createdAt));
    }

    /**
     * 计算SLA剩余时间
     * 
     * @param priority 优先级
     * @param createdAt 工单创建时间
     * @param slaType SLA类型（response/resolution）
     * @return 剩余时间（分钟）
     */
    public long calculateSLARemainingTime(TicketPriority priority, Instant createdAt, String slaType) {
        Instant slaDeadline;
        if ("response".equals(slaType)) {
            slaDeadline = calculateResponseSLA(priority, createdAt);
        } else {
            slaDeadline = calculateResolutionSLA(priority, createdAt);
        }

        Instant now = Instant.now();
        if (now.isAfter(slaDeadline)) {
            return 0; // 已超时
        }

        return Duration.between(now, slaDeadline).toMinutes();
    }

    /**
     * 获取SLA状态描述
     * 
     * @param priority 优先级
     * @param createdAt 工单创建时间
     * @param slaType SLA类型
     * @return SLA状态描述
     */
    public String getSLAStatus(TicketPriority priority, Instant createdAt, String slaType) {
        long remainingMinutes = calculateSLARemainingTime(priority, createdAt, slaType);
        
        if (remainingMinutes <= 0) {
            return "已超时";
        } else if (remainingMinutes <= 60) {
            return "即将超时";
        } else if (remainingMinutes <= 240) { // 4小时
            return "需要关注";
        } else {
            return "正常";
        }
    }

    /**
     * 根据关键词自动确定优先级
     * 
     * @param title 工单标题
     * @param description 工单描述
     * @return 建议的优先级
     */
    public TicketPriority suggestPriorityByContent(String title, String description) {
        String content = (title + " " + description).toLowerCase();

        // 紧急关键词
        if (content.contains("紧急") || content.contains("urgent") || 
            content.contains("崩溃") || content.contains("crash") ||
            content.contains("无法访问") || content.contains("down")) {
            return TicketPriority.URGENT;
        }

        // 高优先级关键词
        if (content.contains("重要") || content.contains("important") ||
            content.contains("影响") || content.contains("影响业务") ||
            content.contains("bug") || content.contains("错误")) {
            return TicketPriority.HIGH;
        }

        // 中优先级关键词
        if (content.contains("功能") || content.contains("feature") ||
            content.contains("改进") || content.contains("enhancement") ||
            content.contains("咨询") || content.contains("question")) {
            return TicketPriority.MEDIUM;
        }

        // 默认低优先级
        return TicketPriority.LOW;
    }

    /**
     * 获取所有优先级配置
     * 
     * @return 优先级配置映射
     */
    public Map<TicketPriority, PriorityConfig> getAllPriorityConfigs() {
        return Map.copyOf(PRIORITY_CONFIGS);
    }

    /**
     * 验证优先级是否有效
     * 
     * @param priority 优先级
     * @return 是否有效
     */
    public boolean isValidPriority(TicketPriority priority) {
        return priority != null && PRIORITY_CONFIGS.containsKey(priority);
    }
}
